/*
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package botobjects;

import interfaces.BotObject;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import main.Constants;

import org.jibble.pircbot.Colors;

import tools.StringTools;

/**
 * This class represents and deals with a summary
 * 
 * 
 */
public class Summary implements BotObject {
   private final Map<String, Integer> selfKD = new HashMap<String, Integer>();
   private final Map<String, Map<String, Integer>> selfProvinces = new HashMap<String, Map<String, Integer>>();
   private final Map<String, Integer> enemyKD = new HashMap<String, Integer>();
   private final Map<String, Map<String, Integer>> enemyProvinces = new HashMap<String, Map<String, Integer>>();

   public void addEnemyHit(final String attackType, final String attacker, final String target, final int ingain,
		 final int amount, final boolean isWar) {
	  if (StringTools.isNullOrEmpty(attackType) || StringTools.isNullOrEmpty(attacker) || StringTools.isNullOrEmpty(target))
		 return;
	  int gain = ingain;
	  selfKD.put("Gains", (selfKD.get("Gains") == null ? -1 * gain * amount : selfKD.get("Gains") - gain * amount));
	  if (selfProvinces.get(target) == null) {
		 selfProvinces.put(target, new HashMap<String, Integer>());
	  }
	  selfProvinces.get(target).put(
			"Gains",
			(selfProvinces.get(target).get("Gains") == null ? -1 * gain * amount : selfProvinces.get(target).get("Gains") - gain
				  * amount));
	  selfProvinces.get(target).put(
			"Hits Received",
			(selfProvinces.get(target).get("Hits Received") == null ? amount : selfProvinces.get(target).get("Hits Received")
				  + amount));
	  if (enemyProvinces.get(attacker) == null) {
		 enemyProvinces.put(attacker, new HashMap<String, Integer>());
	  }
	  if (!"Raze".equals(attackType)) {
		 enemyProvinces.get(attacker).put(
			   "Gains",
			   (enemyProvinces.get(attacker).get("Gains") == null ? gain * amount : enemyProvinces.get(attacker).get("Gains")
					 + gain * amount));
	  }
	  enemyProvinces.get(attacker).put("Hits",
			(enemyProvinces.get(attacker).get("Hits") == null ? amount : enemyProvinces.get(attacker).get("Hits") + amount));
	  if (!"Raze".equals(attackType)) {
		 enemyKD.put("Gains", (enemyKD.get("Gains") == null ? gain * amount : enemyKD.get("Gains") + gain * amount));
	  }
	  enemyKD.put(attackType, (enemyKD.get(attackType) == null ? 1 : enemyKD.get(attackType) + amount));
	  enemyKD.put(attackType + " Gains",
			(enemyKD.get(attackType + " Gains") == null ? gain * amount : enemyKD.get(attackType + " Gains") + gain * amount));
	  enemyKD.put("Hits", (enemyKD.get("Hits") == null ? 1 : enemyKD.get("Hits") + amount));
   }

   private void addHitsOutput(final String hitType, final List<String> list) {
	  if (StringTools.isNullOrEmpty(hitType) || list == null)
		 return;
	  int selfHits = selfKD.get(hitType) == null ? 0 : selfKD.get(hitType);
	  String selfGains = selfKD.get(hitType + " Gains") == null || selfKD.get(hitType + " Gains") == 0 ? "" : " ("
			+ selfKD.get(hitType + " Gains") + "ac)";
	  int enemyHits = enemyKD.get(hitType) == null ? 0 : enemyKD.get(hitType);
	  String enemyGains = enemyKD.get(hitType + " Gains") == null || enemyKD.get(hitType + " Gains") == 0 ? "" : "("
			+ enemyKD.get(hitType + " Gains") + "ac) ";
	  if (!(selfHits == 0 && enemyHits == 0)) {
		 list.add(Colors.OLIVE + hitType + ": " + Colors.NORMAL + selfHits + selfGains + " vs. " + enemyGains + enemyHits);
	  }
   }

   public void addSelfHit(final String attackType, final String attacker, final String target, final int ingain,
		 final int amount, final boolean isWar) {
	  if (StringTools.isNullOrEmpty(attackType) || StringTools.isNullOrEmpty(attacker) || StringTools.isNullOrEmpty(target))
		 return;
	  int gain = ingain;
	  if (!"Raze".equals(attackType)) {
		 selfKD.put("Gains", (selfKD.get("Gains") == null ? gain * amount : selfKD.get("Gains") + gain * amount));
	  }
	  if (selfProvinces.get(attacker) == null) {
		 selfProvinces.put(attacker, new HashMap<String, Integer>());
	  }
	  if (!"Raze".equals(attackType)) {
		 selfProvinces.get(attacker).put(
			   "Gains",
			   (selfProvinces.get(attacker).get("Gains") == null ? gain * amount : selfProvinces.get(attacker).get("Gains")
					 + gain * amount));
	  }
	  selfProvinces.get(attacker).put("Hits",
			(selfProvinces.get(attacker).get("Hits") == null ? amount : selfProvinces.get(attacker).get("Hits") + amount));
	  selfKD.put(attackType + " Gains",
			(selfKD.get(attackType + " Gains") == null ? gain * amount : selfKD.get(attackType + " Gains") + gain * amount));
	  selfKD.put(attackType, (selfKD.get(attackType) == null ? 1 : selfKD.get(attackType) + amount));
	  selfKD.put("Hits", (selfKD.get("Hits") == null ? 1 : selfKD.get("Hits") + amount));

	  enemyKD.put("Gains", (enemyKD.get("Gains") == null ? -1 * gain * amount : enemyKD.get("Gains") - gain * amount));

	  if (enemyProvinces.get(target) == null) {
		 enemyProvinces.put(target, new HashMap<String, Integer>());
	  }
	  enemyProvinces.get(target).put(
			"Gains",
			(enemyProvinces.get(target).get("Gains") == null ? -1 * gain * amount : enemyProvinces.get(target).get("Gains")
				  - gain * amount));
	  enemyProvinces.get(target).put(
			"Hits Received",
			(enemyProvinces.get(target).get("Hits Received") == null ? amount : enemyProvinces.get(target).get("Hits Received")
				  + amount));
   }

   @Override
   public List<String> getIRCOutput(final int outputType, final String... args) {
	  List<String> out = new LinkedList<String>();
	  if (selfKD == null || selfProvinces == null || enemyKD == null || enemyProvinces == null)
		 return out;
	  if (outputType == Constants.SUMMARY_KD) {
		 int selfGains = selfKD.get("Gains") == null ? 0 : selfKD.get("Gains");
		 int enemyGains = enemyKD.get("Gains") == null ? 0 : enemyKD.get("Gains");
		 out.add(Colors.BLUE + "Total Gains: " + (selfGains > 0 ? Colors.DARK_GREEN : selfGains < 0 ? Colors.RED : Colors.NORMAL)
			   + selfGains + Colors.NORMAL + " vs. "
			   + (enemyGains > 0 ? Colors.DARK_GREEN : enemyGains < 0 ? Colors.RED : Colors.NORMAL) + enemyGains);

		 int selfHits = selfKD.get("Hits") == null ? 0 : selfKD.get("Hits");
		 int enemyHits = enemyKD.get("Hits") == null ? 0 : enemyKD.get("Hits");
		 out.add(Colors.OLIVE + "Total Hits: " + Colors.NORMAL + selfHits + " vs. " + enemyHits);

		 addHitsOutput("TM", out);
		 addHitsOutput("Ambush", out);
		 addHitsOutput("Conquest", out);
		 addHitsOutput("Plunder", out);
		 addHitsOutput("Massacre", out);
		 addHitsOutput("Raze", out);
		 addHitsOutput("Learn", out);
		 addHitsOutput("Bounce", out);
	  } else if (outputType == Constants.SUMMARY_PROVINCE && args.length == 1) {
		 Map<String, Integer> province = selfProvinces.get(args[0]) == null ? enemyProvinces.get(args[0]) : selfProvinces
			   .get(args[0]);
		 if (province == null)
			return out;
		 int selfGains = province.get("Gains") == null ? 0 : province.get("Gains");
		 int selfHits = province.get("Hits") == null ? 0 : province.get("Hits");
		 int enemyHits = province.get("Hits Received") == null ? 0 : province.get("Hits Received");
		 out.add(Colors.BLUE + "Total Gains: " + (selfGains > 0 ? Colors.DARK_GREEN : selfGains < 0 ? Colors.RED : Colors.NORMAL)
			   + selfGains + Colors.NORMAL + " (" + selfHits + "/" + enemyHits + ")");
	  }
	  return out;
   }

   public Map<String, Object> getRPCOutput(final int... includes) {
	  Map<String, Object> out = new HashMap<String, Object>();
	  if (selfKD == null || selfProvinces == null || enemyKD == null || enemyProvinces == null)
		 return out;
	  out.put("Self KD", selfKD);
	  out.put("Enemy KD", enemyKD);
	  out.put("Self Provinces", selfProvinces);
	  out.put("Enemy Provinces", enemyProvinces);
	  return out;
   }

   public boolean saveToDB() {
	  return false;
   }
}
